特定の被共有中 Transit Gateway への VPC アタッチメント作成を SCP で禁止してみた

特定の被共有中 Transit Gateway への VPC アタッチメント作成を SCP で禁止してみた

Clock Icon2025.01.12

いわさです。

AWS Transit Gateway は RAM (AWS Resource Access Manager)経由で組織や外部 AWS アカウントを共有することが出来ます。
この時、特定 OU 内からこの Transit Gateway の利用を禁止したい場合に SCP で制限出来るのかを確認してみましたのでその様子を紹介します。

やりたいこと

今回やりたいことですが、Organizations 内のあるアカウントで Transit Gateway を管理しているとして、それを RAM 経由で組織に共有した際に特定の OU から利用出来ないようにしたいなと思っています。

6E43F0D7-55C6-4BBD-ABF7-17BE2F794795.png

Transit Gateway の各イベントログを確認

OU 配下を禁止させたいので、まぁ SCP を使うことになりそうです。
そして SCP を使うためにはどのアクションをどう制御するのか把握したいところです。

ということで先程やりたいことと同じようなOU/アカウント構成を用意して Transit Gateway の作成と共有、共有先アカウントからの利用を行ってみます。
そして CloudTrail ログなどを確認してみましょう。

3DA7E749-F5D6-4F13-96CD-24FDC779B488.png

Transit Gateway を作成後に共有する

Account1 で Transit Gateway を作成後に、他のアカウントへ共有を行います。
「Transit Gateway を共有する」という機能を使って共有を行うのですが、RAM で作成したリソース共有を指定する形です。よって Transit Gateway の共有範囲は RAM の設定次第という感じです。

7FED8253-D424-4F72-9673-2A8A5F50C502.png

RAM では共有リソースを作成し、その際にプリンシパルを指定します。
このプリンシパルが色々な指定方法があり、組織内に限らず指定することも可能です。組織内の場合でも AWS アカウント ID から組織 ID まで様々なスコープを指定することが出来ます。

26722EC4-4A23-4BE2-A964-3619DAFC14DC.png

今回は外部プリンシパルを許可しないかつ自分の組織 ID を指定しました。

77F0D40C-08A3-497E-9BE0-55EB4DF66D6D.png

この時、CreateResourceShareが実行されていました。
関係しそうなパラメータのみ抜粋したイベントデータが次のものです。(プロパティを便宜上削除しています)

{
    "eventVersion": "1.09",
    "userIdentity": { ... },
    "eventSource": "ram.amazonaws.com",
    "eventName": "CreateResourceShare",
    "awsRegion": "ap-northeast-1",
    "requestParameters": {
        "name": "hoge0122ram",
        "resourceArns": [],
        "principals": [],
        "permissionArns": [],
        "allowExternalPrincipals": false,
        "tags": []
    },
    "responseElements": {
        "resourceShare": {
            "allowExternalPrincipals": false,
            "creationTime": 1736637374.383,
            "lastUpdatedTime": 1736637374.383,
            "name": "hoge0122ram",
            "owningAccountId": "xxxxxxxxxxx1",
            "resourceShareArn": "arn:aws:ram:ap-northeast-1:xxxxxxxxxxx1:resource-share/8f1737ca-98ca-4786-849a-ed65d84b116d",
            "status": "ACTIVE",
            "tags": []
        }
    },
    "readOnly": false,
    "eventType": "AwsApiCall",
    "managementEvent": true,
}

RAM でリソース共有が作成出来たら、Transit Gateway の共有機能で指定します。

FE4B6579-94C4-4DC4-A2E1-535B190F5295.png

この時は、AssociateResourceShareが実行されていました。

{
    "eventVersion": "1.09",
    "userIdentity": { ... },
    "eventSource": "ram.amazonaws.com",
    "eventName": "AssociateResourceShare",
    "awsRegion": "ap-northeast-1",
    "requestParameters": {
        "resourceShareArn": "arn:aws:ram:ap-northeast-1:xxxxxxxxxxx1:resource-share/8f1737ca-98ca-4786-849a-ed65d84b116d",
        "resourceArns": [
            "arn:aws:ec2:ap-northeast-1:xxxxxxxxxxx1:transit-gateway/tgw-022576db7e6c1f206"
        ]
    },
    "responseElements": {
        "resourceShareAssociations": [
            {
                "associatedEntity": "arn:aws:ec2:ap-northeast-1:xxxxxxxxxxx1:transit-gateway/tgw-022576db7e6c1f206",
                "associationType": "RESOURCE",
                "external": false,
                "resourceShareArn": "arn:aws:ram:ap-northeast-1:xxxxxxxxxxx1:resource-share/8f1737ca-98ca-4786-849a-ed65d84b116d",
                "status": "ASSOCIATING"
            }
        ]
    },
    "readOnly": false,
    "eventType": "AwsApiCall",
    "managementEvent": true
}

この時点で、組織内のどのアカウントからも Transit Gateway コンソールから共有された Transit Gateway の情報を参照出来るようになります。利用を禁止したい OU 配下のアカウントからは次のように確認が出来ます。なるほど。

022072D4-2587-4C9B-B922-08858A86C297.png

共有された側でアタッチメントを作成する

ではこの Account5 から利用してみます。
まずは VPC アタッチメントを作成してみます。ここは共有側のアカウントでは作成できず、関連付けする VPC を所有しているアカウントが作成する必要があります。

B9ECBAC8-DF93-4B99-8626-2994BE455F2F.png

この時、CreateTransitGatewayVpcAttachmentが実行されます。

{
    "eventVersion": "1.10",
    "userIdentity": { ... },
    "eventSource": "ec2.amazonaws.com",
    "eventName": "CreateTransitGatewayVpcAttachment",
    "awsRegion": "ap-northeast-1",
    "requestParameters": {
        "CreateTransitGatewayVpcAttachmentRequest": {
            "Options": {
                "Ipv6Support": "disable",
                "ApplianceModeSupport": "disable",
                "SecurityGroupReferencingSupport": "enable",
                "DnsSupport": "enable"
            },
            "TransitGatewayId": "tgw-022576db7e6c1f206",
            "VpcId": "vpc-0258c46d8ab83eab6",
            "TagSpecifications": {
                "ResourceType": "transit-gateway-attachment",
                "tag": 1,
                "Tag": {
                    "Value": "hoge0112attachment",
                    "tag": 1,
                    "Key": "Name"
                }
            },
            "SubnetIds": {
                "tag": 1,
                "content": "subnet-017f98ea9b740e73b"
            }
        }
    },
    "responseElements": {
        "CreateTransitGatewayVpcAttachmentResponse": {
            "xmlns": "http://ec2.amazonaws.com/doc/2016-11-15/",
            "transitGatewayVpcAttachment": {
                "tagSet": {
                    "item": {
                        "value": "hoge0112attachment",
                        "key": "Name"
                    }
                },
                "creationTime": "2025-01-11T23:23:24.000Z",
                "transitGatewayAttachmentId": "tgw-attach-01331730939385c4f",
                "transitGatewayId": "tgw-022576db7e6c1f206",
                "vpcId": "vpc-0258c46d8ab83eab6",
                "options": {
                    "applianceModeSupport": "disable",
                    "securityGroupReferencingSupport": "enable",
                    "dnsSupport": "enable",
                    "ipv6Support": "disable"
                },
                "state": "pendingAcceptance",
                "vpcOwnerId": "xxxxxxxxxxx5",
                "subnetIds": {
                    "item": "subnet-017f98ea9b740e73b"
                }
            },
            "requestId": "960dca5b-8c97-4c9b-972b-2c09eef78fc3"
        }
    },
    "readOnly": false,
    "eventType": "AwsApiCall",
    "managementEvent": true
}

この作成しただけだとまだアタッチメントは使うことが出来ません。ステータスがPending Acceptanceとなっています。
ということで、Transit Gateway の所有者に承認してもらう必要があります。

9DED3319-6D8C-41A1-90AD-4777C99B6021.png

このとき、AcceptTransitGatewayVpcAttachmentが実行されます。

{
    "eventVersion": "1.10",
    "userIdentity": { ... },
    "eventSource": "ec2.amazonaws.com",
    "eventName": "AcceptTransitGatewayVpcAttachment",
    "awsRegion": "ap-northeast-1",
    "requestParameters": {
        "AcceptTransitGatewayVpcAttachmentRequest": {
            "TransitGatewayAttachmentId": "tgw-attach-01331730939385c4f"
        }
    },
    "responseElements": {
        "AcceptTransitGatewayVpcAttachmentResponse": {
            "xmlns": "http://ec2.amazonaws.com/doc/2016-11-15/",
            "transitGatewayVpcAttachment": {
                "transitGatewayAttachmentId": "tgw-attach-01331730939385c4f",
                "transitGatewayId": "tgw-022576db7e6c1f206",
                "vpcId": "vpc-0258c46d8ab83eab6",
                "state": "pending",
                "vpcOwnerId": "xxxxxxxxxxx5",
                "subnetIds": {
                    "item": "subnet-017f98ea9b740e73b"
                }
            },
            "requestId": "ced4f370-ab42-4408-a9a0-ecdb50ea2108"
        }
    }
}

ちなみに、Transit Gateway の「共有アタッチメントの自動承認」機能を有効化すると、この承認をスキップして自動承認させることが出来ます。

85A6D540-30E3-4AF4-965D-14F0E3BF06B9.png

この時、CloudTrail イベントを観察する限りではAcceptTransitGatewayVpcAttachmentが発生せずに、CreateTransitGatewayVpcAttachment直後ステータスがそのまま承認状態となります。

SCP で制限してみる

さて、アタッチメントが使えるようになるまでのイベントが整理出来たので SCP で制御してみます。
先ほどまでで以下の流れであることがわかりました。

  • Transit Gateway を共有
    • RAM を共有(スコープは自由自在): CreateResourceShare
    • Transit Gateway 共有機能で RAM リソースを指定する: AssociateResourceShare
  • Transit Gateway アタッチメントを作成
    • 使いたい側からアタッチメントを作成する: CreateTransitGatewayVpcAttachment
    • 管理側から承諾する(省略オプションあり): AcceptTransitGatewayVpcAttachment

今回は特定 Transit Gateway に対するアタッチメントの作成を禁止してみようかなと思います。

というのも、共有周りの制限も出来そうですが、複雑なポリシー実装になりそうな気がしているのと、既に共有済みの環境だと利用中の Transit Gateway に対する共有設定を変更する必要がありそうです。
また、アタッチメントの承諾部分を制御することも出来そうですが、ここも自動承諾機能があるので今回は一旦忘れます(対処しない)
また、厳密にはアタッチメント作成後にルートテーブルの関連付けなどもあるのですが、このあたりもデフォルトリソースの概念があるので今回はここも対応しません。

ということで、今回はCreateTransitGatewayVpcAttachmentアクションを禁止するポリシーを作成できれば良さそうです。
ただし、特定の Transit Gateway のみを制限するようにしたいと思います。Account1 から共有された以外の Transit Gateway については共有利用を許可したい場合があり得るからです。

これを行うためには IAM アクションごとの条件キーを確認する必要があります。
次のドキュメントのCreateTransitGatewayVpcAttachmentアクションの諸々を確認してみましょう。

https://docs.aws.amazon.com/ja_jp/IAM/latest/UserGuide/list_amazonec2.html#amazonec2-actions-as-permissions

指定出来る条件キーは以下のようです。

  • subnet*
    • aws:ResourceTag/${TagKey}
    • ec2:AvailabilityZone
    • ec2:ResourceTag/${TagKey}
    • ec2:SubnetID
    • ec2:Vpc
  • vpc*
    • aws:ResourceTag/${TagKey}
    • ec2:ResourceTag/${TagKey}
    • ec2:Tenancy
    • ec2:VpcID
  • transit-gateway*
    • aws:ResourceTag/${TagKey}
    • ec2:ResourceTag/${TagKey}
    • ec2:transitGatewayId

ec2:transitGatewayIdが指定出来るのでこれで制限をかけれそうです。Transit Gateway の ID を指定出来そう。
あるいはタグを使った ABAC もありかもしれないですね。

次のように制限したい Transit Gateway ID を指定した SCP を作成して OU にアタッチします。

6017B6E0-05B1-42DA-ABD5-370AB88E99CD.png

もう一度アタッチメントを作成しようとすると SCP がアタッチされた OU 配下のアカウントでは作成に失敗しました。一方で SCP がアタッチされていない OU では作成に成功します。

DDC1CDA5-8D7D-4E8C-959B-FFF968073B27.png

さらに、SCP がアタッチされた OU でも他の Transit Gateway へのアタッチメント作成は出来ました。良い感じです。

DA804532-D7EC-4E68-8756-D836F2DFA42E.png

さいごに

本日は特定の被共有中 Transit Gateway への VPC アタッチメント作成を SCP で禁止してみました。

アタッチメント作成が出来ないので OU 配下で特定の Transit Gateway を使った通信は禁止出来る気がします。
一方で、Transit Gateway の情報参照もさせたくない場合(例えば組織内に Transit Gateway が存在することを認識させたくない場合)は RAM の共有部分を制御する必要がありそうです。このあたりも別途コントロール方法を調べてみようかなと思います。

Share this article

facebook logohatena logotwitter logo

© Classmethod, Inc. All rights reserved.